package de.tum.in.eist.im.client.Chat;

import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowCloseListener;
import com.google.gwt.user.client.rpc.AsyncCallback;

import de.tum.in.eist.im.client.Chat.ChatPanelService;
import de.tum.in.eist.im.client.Chat.ChatPanelServiceAsync;
import de.tum.in.eist.im.client.Chat.CreateChatChannelTab.CreateChatChannelTab;
import de.tum.in.eist.im.shared.ChatChannel.ChatChannel;
import de.tum.in.eist.im.shared.User.User;

@SuppressWarnings("deprecation")
public class ChatUIHandler implements WindowCloseListener {
	
	// private variables
	private final static ChatPanelServiceAsync chatPanelService = GWT.create(ChatPanelService.class);
	private final ChatUI chatUI;
	private final User user;
	
	/**
	 * constructor for the chat panel handler
	 * @param channelTitle the title of the channel
	 * @param chatUI the chatUI
	 * @param user the user
	 */
	public ChatUIHandler(ChatUI chatUI, User user) {
		this.chatUI = chatUI;
		this.user = user;
		this.getOnlineUsersFromServer();
		this.getOpenGroups();
		
		Window.addWindowCloseListener(this);
		ChatUIHandler.this.addUserAsOnline();
	}
	
	/** 
	 * get the id of a group of the server. if the group already existed return the old id else create
	 * a new one on the server
	 */
	public void getChannelId(final String channelTitle) {
		// get channel id
		chatPanelService.getChatChannelId(
			channelTitle,
			new AsyncCallback<Long>() {
				public void onFailure(Throwable caught) {
					System.out.println(">>> ChatPanelHandler: cannot get channel id!");
				}
				
				public void onSuccess(Long result) {
					ChatUIHandler.this.addGroupAsOpen(channelTitle, result);
				}
			});
	}
	
	/**
	 * get the private chat id of two user	
	 * @param thisUser the user opening the private chat
	 * @param otherUser the user user
	 */
	public void getPrivateChatChannelId(User thisUser, User otherUser) {
		// get private chat channel id
		chatPanelService.getPrivateChatChannelId(
			thisUser,
			otherUser,
			new AsyncCallback<Long>() {

				@Override
				public void onFailure(Throwable caught) {
					System.out.println("Failure in getPrivatChatChannelId: " + caught.getMessage());
				}

				@Override
				public void onSuccess(Long result) {
					System.out.println("RESULT: " + result.toString());
				}
				
			}
		);
	}
	
	/**
	 * add a channel to the list of open channels
	 * @param channelTitle the title of the channel
	 * @param result the if of the chat channel
	 */
	public void addGroupAsOpen(final String channelTitle, final Long channelId) {
		ChatChannel groupChat = new ChatChannel(channelId, channelTitle);
		groupChat.addUserToChatChannel(user);
		user.addOpenChatChannel(groupChat);
		
		// add group as open
		chatPanelService.addGroupAsOpen(
				groupChat,
				new AsyncCallback<Boolean>() {
					@Override
					public void onFailure(Throwable caught) {
						System.out.println("Error in addGroupAsOpen method");
					}

					@Override
					public void onSuccess(Boolean result) {
						// so open it
						chatUI.addChatTab(channelTitle, channelId);
						CreateChatChannelTab.getCreateGroupButton().setEnabled(true);
					}
				}
		);
		
	}
	
	/**
	 * Poll the list of open groups and display them on the chatPanel!
	 * So we implemented a push system and a poll system
	 * Why do we need a poll here: The push system creates threads on the server we cannot be sure
	 * that one connection can create multiple threads on the server
	 */
	public void getOpenGroups() {
		Timer timer = new Timer() {
			@Override
			public void run() {
				chatPanelService.getOpenGroups(
						new AsyncCallback<List<ChatChannel>>() {

							@Override
							public void onFailure(Throwable caught) {
								System.out.println("Error in getOnlineUsersFromServer()");
							}

							@Override
							public void onSuccess(List<ChatChannel> result) {
								chatUI.clearListOfChatChannels();
								for (ChatChannel cC : result) {
									/*
									System.out.println("Group: " + cC.getTitle());
									System.out.println("User in Group: ");
									for (User u : cC.getUserInChannel())
										System.out.println(">> " + u.getUsername());
										*/
									chatUI.addChatChannelToListOfOpenChannels(cC);
								}
								ChatUIHandler.this.getOpenGroups();
							}	
						}
				);	
			}
		};
		// poll for users every 0.5 seconds
		timer.schedule(500);
	}
	
	/**
	 * add a user to the list of online users
	 */
	public void addUserAsOnline() {
		// add user to channel
		chatPanelService.addUserAsOnline(
			user,
			new AsyncCallback<Boolean>() {
				public void onFailure(Throwable caught) {
					System.out.println(">>> ChatPanelHandler: cannot add user to list!");
				}
				
				public void onSuccess(Boolean result) {
					// display panel with all user and start push for user session
				}
			});
	}
	
	/**
	 * remove a user of the list of online users
	 */
	public void removeUserAsOnline() {
		// remove user from channel
		chatPanelService.removeUserAsOnline(
				user, 
				new AsyncCallback<Boolean>() {
					public void onFailure(Throwable caught) {
						System.out.println(" cannot remove user from list!");
					}
					
					public void onSuccess(Boolean result) {
						
					}
				}
		);
	}
	
	/**
	 * Poll the list of users and display them on the chatPanel!
	 * So we implemented a push system and a poll system
	 * Why do we need a poll here: The push system creates threads on the server we cannot be sure
	 * that one connection can create multiple threads on the server
	 */
	public void getOnlineUsersFromServer() {
		Timer timer = new Timer() {
			@Override
			public void run() {
				chatPanelService.getOnlineUsersFromServer(
						new AsyncCallback<List<User>>() {

							@Override
							public void onFailure(Throwable caught) {
								System.out.println("Error in getOnlineUsersFromServer()");
							}

							@Override
							public void onSuccess(List<User> result) {
								chatUI.clearListOfOnlineUser();
								for (User user : result) {
									chatUI.addUserToListOfOnlineUser(user);
								}
								ChatUIHandler.this.getOnlineUsersFromServer();
							}	
						}
				);	
			}
		};
		// poll for users every 0.5 seconds
		timer.schedule(500);
	}
	
	@Override
	public String onWindowClosing() {
		return null;
	}

	@Override
	public void onWindowClosed() {
		this.removeUserAsOnline();
	}
}
